#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "dfs_messages.h"
#include "dfs_client.h"

/* Builds a message according to it's parameters */
int build_message(dfs_message *m,const char *sender,const char *receiver,int kind,int type,const char *data){
	int r;
	/* First clear message */
	memset(m->sender,0,sizeof(m->sender));
	memset(m->receiver,0,sizeof(m->receiver));
	memset(m->data,0,sizeof(m->data));
	
	/*Form message */
	r = sprintf(m->sender,"%s",sender);
	if( r < 0) return (ERROR);
	r = sprintf(m->receiver,"%s",receiver);
	if( r < 0) return (ERROR);
	m->kind = kind;
	m->type = type;
	r = sprintf(m->data,"%s",data);
	if (r< 0) return (ERROR);
	
	/* message built */
	return (OK);
}

/* Serializes a message to be sent among servers*/
int message_to_string(dfs_message *m,char *str){
	int r;
	r = sprintf(str,"%s|%s|%d|%d[%s",m->sender
									 	,m->receiver
									 	,m->kind
									 	,m->type
									 	,m->data);
									
	if(r < 0 ) return (ERROR);
	else return (OK);
}

/* Deserializes a message sent among servers */
int string_to_message(dfs_message *m,char *str){
	char *result;
	char *oob;
	int i,olen,dlen,r,kind,type;
	char sender[MAXIPADDRESSLEN];
	char receiver[MAXIPADDRESSLEN];
	char data[DATA_SIZE];	
	/*init */
	result = NULL;
	memset(sender,0,MAXIPADDRESSLEN);
	memset(receiver,0,MAXIPADDRESSLEN);
	memset(data,0,DATA_SIZE);
	
	/* Retrieve OOB */
	result = strtok(str,"[");
	if(result == NULL) return (ERROR);
	olen = strlen(result);
	oob = malloc(olen*sizeof(char));
	memset(oob,0,olen);
	sprintf(oob,"%s",result);
	for(i=0;i<olen;i++) if(oob[i]=='|') oob[i] = ' ';

	r = sscanf(oob,"%s %s %d %d",sender
								,receiver
								,&kind
								,&type);
	if (r < 4) return (ERROR);

	/* Retrieve data */
	result = strtok(NULL,"[");
	if(result == NULL) r = sprintf(data,"");
	else r = sprintf(data,"%s",result);
	if(r < 0) return (ERROR);

	/* build message */
	if (build_message(m,sender,receiver,kind,type,data) < 0) return (ERROR);
	
	/* free vars */
	free(oob);
	
	return (OK);
}

/* create an OK reply message */
void make_OK_reply_message(dfs_message *m,const char *reply_to_addr){
	build_message(m,my_ip_address,reply_to_addr,REPL_KIND,OK_MSG,"");
}

/* create an ERROR reply message */
void make_ER_reply_message(dfs_message *m,const char *reply_to_addr){
	build_message(m,my_ip_address,reply_to_addr,REPL_KIND,ER_MSG,"");
}

/* determine what type of reply message was received */
int handle_in_message(dfs_message *m_in){
	if(m_in->kind == COMD_KIND){
		/* message is command */
		switch(m_in->type){
			default:
				printf("[msg handling for type %d not not implemented yet!\n]",m_in->type);
				return ERROR;
				break;
		}
	}else if(m_in->kind == DATA_KIND){
		/* mesasge is data */
		printf("[msg handling for DATA_KIND is not yet implemented]\n");
		return (ERROR);
	}else if(m_in->kind == REPL_KIND){
		/* message is reply */
		switch(m_in->type){
			case OK_MSG:
				return OK;
				break;
			case ER_MSG:
				return ERROR;
				break;
			case UNKNOWN_MSG: 
				printf("[UNKNOWN_MSG reply message received]\n");
				return ERROR;
				break;
			case RR_MSG:
				if(strlen(m_in->data) == 0) printf("[No files to share]\n");
				else printf("[=====]\n%s\n[=====]\n",m_in->data);
				return OK;
				break;
		}
	}
}

/* builds a message for sending to server in order to connect to a peer server */
int make_connect_p2p_msg(dfs_message *m,const char *ipaddr,const char *port,const char *connected_server){
	char data[DATA_SIZE];
	
	/* set data */
	memset(data,0,DATA_SIZE);
	sprintf(data,"%s %s",ipaddr,port);
	if(build_message(m,my_ip_address,connected_server,COMD_KIND,CON_PEER_MSG,data) < 0) return (ERROR);
}
/* builds a message for sending which file to share to the rest of the network */
int make_sharing_msg(dfs_message *m,const char *alias,const char *connected_server){
	char data[DATA_SIZE];
	
	/* set data */
	memset(data,0,DATA_SIZE);
	sprintf(data,"%s",alias);
	if(build_message(m,my_ip_address,connected_server,COMD_KIND,GET_SFI_MSG,data) < 0) return (ERROR);
}
/* builds a message for sending which file to remove from it's sharing list */
int make_rmfile_msg(dfs_message *m,const char *alias,const char *connected_server){
	char data[DATA_SIZE];
	
	/* set data */
	memset(data,0,DATA_SIZE);
	sprintf(data,"%s",alias);
	if(build_message(m,my_ip_address,connected_server,COMD_KIND,REM_SFI_MSG,data) < 0) return (ERROR);
}
/* builds a message for in order to get sharing file list */
int make_get_files_msg(dfs_message *m,const char *connected_server){
	if(build_message(m,my_ip_address,connected_server,COMD_KIND,LIS_SFI_MSG,"") < 0) return (ERROR);
}
/* builds a message so as to open a distributed file */
int make_open_msg(dfs_message *m,const char *alias,const char *connected_server){
	if(build_message(m,my_ip_address,connected_server,COMD_KIND,OP_FILE_MSG,alias) < 0) return (ERROR);
}